<?php
/**
 * @Author: gan
 * @Description: 本地
 * @File:  LocalAdapter
 * @Version: 1.0.0
 * @Date: 2021/12/27 9:15 上午
 */
declare(strict_types=1);

namespace RX\Component\Upload\Impl;

use EasySwoole\Http\Message\UploadFile;
use EasySwoole\Http\Request;
use RX\Enums\UploadEnum;
use RX\Exception\BizException;
use RX\Helpers\FileHelper;
use RX\Helpers\RandomHelper;
use RX\Helpers\StringHelper;

class LocalImpl implements UploadInterface
{
    private string $dir;
    private string $domain;

    // 文件类型
    public string $fileType = 'image';

    // 上传最大大小
    public $maxSize = 2 * 1024;

    // 文件后缀类型
    public $fileExtTypes = [
        'png',
        'gif',
        'jpg',
        'jpeg',
    ];

    public function __construct(array $config = [])
    {
        if (empty($config)) {
            $config = StringHelper::config('upload.local');
        }
        $this->dir          = $config["dir"] ?? "/Static/";
        $this->maxSize      = $config["maxSize"];
        $this->fileExtTypes = $config["ext"];
        $this->domain       = $config["domain"] ?? "";
    }

    public function stsData()
    {
        return [];
    }


    public function uploadFile(array $params)
    {
        if (empty($params["request"]) || !($params["request"] instanceof Request)) {
            throw new BizException(UploadEnum::class, UploadEnum::PUT_OBJECT_PARAMS_ERROR);
        }

        // file object
        /**
         * @var $file UploadFile
         */
        $file = $params["request"]->getUploadedFile($this->fileType);

        // check size
        $size = $file->getSize();
        $this->checkSize($size);

        // check ext
        $fileName = $file->getClientFileName();
        $ext      = $file->getClientMediaType();
        $this->checkMediaType($ext);

        $saveName = $this->getFile($fileName);
        $result   = $file->moveTo($saveName["targetPath"]);
        if (empty($result)) {
            unset($saveName["targetPath"]);
            return $saveName;
        }
        return null;
    }


    private function getFile(string $fileName)
    {
        $pathInfo  = pathinfo($fileName);
        $extension = $pathInfo['extension'];

        $dirname = date('Y') . DIRECTORY_SEPARATOR . date("m") . DIRECTORY_SEPARATOR;
        $dir     = EASYSWOOLE_ROOT . $this->dir . $dirname;
        if (!is_dir($dir)) {
            FileHelper::createDirectory($dir, 0777);
        }
        $filename = RandomHelper::makeSnowFlake(date("YmdHis")) . uniqid() . "." . $extension;
        return [
            "fileName"   => $filename,
            "filePath"   => $this->dir . $dirname . $filename,
            "targetPath" => $dir . $filename,
            "fullPath"   => $this->domain . $this->dir . $dirname . $filename
        ];
    }


    /**
     * 检测文件大小
     * @param int $size 大小
     * @return bool
     * @throws BizException
     */
    public function checkSize(int $size)
    {
        if (empty($size)) {
            throw new BizException(UploadEnum::class, UploadEnum::MAX_SIZE_ERROR);
        }
        if ($size > $this->maxSize) {
            throw new BizException(UploadEnum::class, UploadEnum::MAX_SIZE_ERROR);
        }
        return true;
    }


    /**
     * 检测文件media type
     * @param string $ext
     * @return bool
     * @throws BizException
     */
    public function checkMediaType(string $ext)
    {
        $mType = explode('/', $ext);
        $mType = $mType[1] ?? "";
        if (empty($mType)) {
            throw new BizException(UploadEnum::class, UploadEnum::EXT_ERROR);
        }
        if (!in_array($mType, $this->fileExtTypes)) {
            throw new BizException(UploadEnum::class, UploadEnum::EXT_ERROR);
        }
        return true;
    }

    public function domain()
    {
        return $this->domain;
    }
}
